package monitor_config

import (
	"crypto/md5"
	"encoding/hex"
	"fmt"
	"github.com/fsnotify/fsnotify"
	c "github.com/spf13/viper"
	"os"
)

/*
	github.com/spf13/viper 是一个在 Go 语言中广泛使用的配置管理库，
	它提供了一种简单的方式来管理和存储应用程序的配置。
	Viper 支持多种配置文件格式，如 JSON、TOML、YAML、HCL，以及 Java properties 文件。
	它还支持从环境变量、命令行参数、远程配置系统（如 etcd 或 Consul）和键值存储中读取配置信息。
	Viper 的特点包括：
		*设置默认值
		*支持多种配置文件格式
		*实时监控配置文件的更改并重新加载
		*支持环境变量
		*支持远程配置系统
		*支持读取命令行参数
		*支持显式设置键值
*/

// FuncConfigChange 配置文件修改声明
type FuncConfigChange func(fsnotify.Event)

// configChangeFunc_ 注册私有回调函数列表
var configChangeFunc_ []FuncConfigChange

// configMd5_ 私有变量MD5默认空字符串
var configMd5_ string = ""

// Initialize 初始化加载配置
func Initialize() error {
	// 监听配置文件修改
	c.WatchConfig()
	c.OnConfigChange(watchConfigChange)
	return nil
}

// AddConfigChangeCbk 添加配置变更回调函数
func AddConfigChangeCbk(in FuncConfigChange) {
	configChangeFunc_ = append(configChangeFunc_, in)
}

// readConfigFileMd5 读取配置文件Md5值
func readConfigFileMd5(filename string) string {
	s, err := os.ReadFile(filename)
	if err != nil {
		return ""
	}
	// 创建一个md5的哈希对象，用于计算哈希值
	m := md5.New()
	// 将文件内容写入md5哈希对象
	m.Write([]byte(s))
	// 使用 m.Sum(nil) 计算最终的 MD5 哈希值。Sum 方法返回一个字节切片，表示哈希值。然后使用 hex.EncodeToString 将字节切片转换为十六进制字符串，以便于阅读和存储。
	return hex.EncodeToString(m.Sum(nil))
}

// watch 监听配置文件修改
func watchConfigChange(e fsnotify.Event) {
	// 修改一次文件，这个接口会通知多次，原因没有细究。通知过后，缓存中的配置项数据已经被修改。
	// util.LogSrv.Debug("[MonitorConfig]: Config file is changed: %s", e.String())
	// util.LogSrv.Debug("[MonitorConfig]: Config file is changed: %s", e.Name)

	// 通过比对配置文件的md5值，来判断文件是否相同
	newMd5 := readConfigFileMd5(e.Name)
	if configMd5_ == newMd5 {
		return
	}
	configMd5_ = newMd5
	fmt.Printf("[MonitorConfig]: Config file is changed: FileName => [%s], change => [%s]", e.Name, e.String())
	for _, cbk := range configChangeFunc_ {
		cbk(e)
	}
}

// MonitorConfigChange 监听配置文件改变
func MonitorConfigChange(e fsnotify.Event) {
	fmt.Println("[MonitorConfig]: Deal config changed!")
	// 重新加载配置文件
}

func Main() {
	Initialize()
	AddConfigChangeCbk(MonitorConfigChange)
}
